home *** CD-ROM | disk | FTP | other *** search
- #include "stdafx.h"
-
- cBMP *bitmaps = 0;
-
- cBMP::cBMP(int _w, int _h, char *_name)
- {
- // Set variables
-
- w = _w;
- h = _h;
- usedcount = 0;
- dds_vid = 0;
-
- // Set name
-
- name = strdup(_name);
-
- // Create surface
-
- if ((dds = create_surface(w, h, DDSCAPS_SYSTEMMEMORY, DDSD_CKSRCBLT)) == 0)
- error("Unable to create surface for %s", name);
-
- // Add image to list
-
- add((cList **)&bitmaps);
- }
-
- cBMP::~cBMP()
- {
- free(name);
- safe_release(&dds);
- safe_release(&dds_vid);
- }
-
- void cBMP::reset()
- {
- for (cBMP *b = bitmaps; b != 0; b = (cBMP *)b->next)
- {
- safe_release(&b->dds_vid);
- b->usedcount = 0;
- }
- }
-
- LPDIRECTDRAWSURFACE4 cBMP::bestptr(cSurface *dest)
- {
- // If we don't have the caps don't bother putting things in video memory
-
- if (no_blit_hardware || !hardware_blit_caps || (dest->caps.dwCaps & DDSCAPS_SYSTEMMEMORY))
- return dds;
-
- // Increase usedcount
-
- usedcount++;
-
- // Resort, least used images first
-
- sort(&this_minus_other_usedcount);
-
- // Return pointer
-
- return dds_vid != 0? dds_vid:dds;
- }
-
- int cBMP::this_minus_other_usedcount(cList *t, cList *o)
- {
- return ((cBMP *)t)->usedcount - ((cBMP *)o)->usedcount;
- }
-
- void cBMP::make_dynamic_use_of_video_mem()
- {
- // If we don't have the right blit caps then don't bother putting things in video memory
-
- if (no_blit_hardware || !hardware_blit_caps)
- return;
-
- // Get end of list
-
- cBMP *e = (cBMP *)cList::get_end((cList *)bitmaps);
-
- // No images or none ever used
-
- if (e == 0 || e->usedcount <= 0)
- return;
-
- // Try to find an image that could be blit to video memory
-
- for (; e != bitmaps && e->dds_vid != 0; e = (cBMP *)e->prev);
-
- // All images are in video memory or no more used images, good!
-
- if (e == bitmaps || e->usedcount <= 0)
- return;
-
- // Allocate image
-
- e->dds_vid = create_surface(e->w, e->h, DDSCAPS_VIDEOMEMORY, DDSD_CKSRCBLT);
-
- if (e->dds_vid != 0)
- {
- // Image created, now blit the contents to video memory
-
- while (FAILED(e->dds_vid->BltFast(0, 0, e->dds, 0, DDBLTFAST_WAIT)))
- if (FAILED(e->dds->Restore()) || FAILED(e->dds_vid->Restore()))
- {
- // Some resource permanently lost
-
- safe_release(&e->dds_vid);
-
- // Exit loop
-
- break;
- }
-
- return;
- }
-
- // Not enough room to allocate surface, search for least used image in video memory
-
- for (cBMP *b = bitmaps; b != e && b->dds_vid == 0; b = (cBMP *)b->next);
-
- // Is there one?
-
- if (b == e)
- {
- // No room for this image, make it very unimportant and resort it
-
- e->usedcount = -100;
- e->relink((cList **)&bitmaps);
-
- return;
- }
-
- // Release this image
-
- safe_release(&b->dds_vid);
- }
-
- static void create_add_file(const char *fn, const char *name)
- {
- // Read the bitmap headers into memory
-
- CFile b;
-
- if (!b.Open(fn, CFile::modeRead | CFile::shareDenyWrite))
- error("Unable to open %s", fn);
-
- BITMAPFILEHEADER bfh;
- b.Read(&bfh, sizeof(bfh));
-
- BITMAPINFOHEADER bih;
- b.Read(&bih, sizeof(bih));
-
- // Check if it's in the right format
-
- if (bfh.bfType != 'MB')
- error("Bitmap %s is not a bitmap", fn);
-
- if (bih.biHeight <= 0)
- error("Bitmap %s is not bottom up", fn);
-
- if (bih.biBitCount != 8)
- error("Bitmap %s is not 8 bit", fn);
-
- if (bih.biCompression != BI_RGB)
- error("Bitmap %s is compressed!", fn);
-
- // Get width of scanline
-
- int w = (bih.biWidth + 3) & ~3;
-
- // Read bitmap data
-
- char *d = new char [bih.biHeight * w];
- b.Seek(bfh.bfOffBits, CFile::begin);
- b.Read(d, bih.biHeight * w);
-
- // Open database file
-
- CFile f;
-
- if (!f.Open("Bitmaps.dat", CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::shareExclusive))
- error("Unable to open Bitmaps.dat");
-
- f.SeekToEnd();
-
- // Write name of object + bytecount of string
-
- int l = strlen(name);
- f.Write(&l, sizeof(l));
- f.Write(name, l);
-
- // Write bitmap width and height
-
- f.Write(&bih.biWidth, sizeof(bih.biWidth));
- f.Write(&bih.biHeight, sizeof(bih.biHeight));
-
- // Write data
-
- for (int y = bih.biHeight - 1; y >= 0; y--)
- f.Write(&d[w * y], bih.biWidth);
-
- // Release temporary space
-
- delete d;
- }
-
- void cBMP::create_file()
- {
- search_files("Bmp", "*.BMP", create_add_file);
- }
-
- void cBMP::load()
- {
- BYTE *data, *d, *s;
- int l, x, y, w, h;
- char name[256];
- CFile f;
-
- // Open bitmaps file
-
- if (!f.Open("Bitmaps.dat", CFile::modeRead | CFile::shareDenyWrite))
- error("Unable to open Bitmaps.dat");
-
- while (f.Read(&l, sizeof(l)) == sizeof(l))
- {
- // Read name
-
- f.Read(name, l);
- name[l] = 0;
-
- // Read dimensions
-
- f.Read(&w, sizeof(w));
- f.Read(&h, sizeof(h));
-
- // Read bitmap data
-
- data = new BYTE [w * h];
- f.Read(data, w * h);
-
- // Create bitmap
-
- cBMP *b = new cBMP(w, h, name);
-
- // Lock the surface for writing bitmap data
-
- DDSURFACEDESC2 ddsd;
-
- ddsd.dwSize = sizeof(ddsd);
-
- if (FAILED(b->dds->Lock(0, &ddsd, DDLOCK_WAIT, 0)))
- error("Unable to lock memory for bitmap load");
-
- // Copy data
-
- s = (BYTE *)ddsd.lpSurface;
- d = data;
-
- switch(ddsd.ddpfPixelFormat.dwRGBBitCount)
- {
- case 8:
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++, s++, d++)
- *s = color_table_this_mode[*d];
-
- s += ddsd.lPitch - w;
- }
- break;
-
- case 16:
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++, s += 2, d++)
- *(WORD *)s = color_table_this_mode[*d];
-
- s += ddsd.lPitch - (w << 1);
- }
- break;
-
- case 24:
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++, s += 3, d++)
- *(WORD *)s = color_table_this_mode[*d],
- s[2] = color_table_this_mode[*d] >> 16;
-
- s += ddsd.lPitch - (w << 1) - w;
- }
- break;
-
- case 32:
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++, s += 4, d++)
- *(DWORD *)s = color_table_this_mode[*d];
-
- s += ddsd.lPitch - (w << 2);
- }
- break;
- }
-
- // Unlock memory
-
- b->dds->Unlock(0);
-
- // Release data
-
- delete data;
- }
- }
-
- cBMP *cBMP::get(char *fn)
- {
- for (cBMP *b = bitmaps; b != 0; b = (cBMP *)b->next)
- if (eq(fn, b->name))
- return b;
-
- error("Image %s not found", fn);
-
- return 0;
- }
-